﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the Microsoft Public License (Ms-PL).
// See accompanying file License.txt or copy at http://mews.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Mews.Net.Nntp.Cache
{
    using System;
    using System.Data.SqlServerCe;

    /// <summary>Provides the means to update hosts fast.</summary>
    internal sealed class HostUpdater : IDisposable
    {
        private static readonly string[] userNameColumn = { HostNames.UserNameColumn };
        private static readonly string[] emailAddressColumn = { HostNames.EmailAddressColumn };
        private static readonly string[] accountNameColumn = { HostNames.AccountNameColumn };
        private static readonly string[] passwordColumn = { HostNames.PasswordColumn };

        private readonly SqlCeCommand command;
        private readonly SqlCeResultSet resultSet;

        private readonly int hostNameMaxLength;
        private readonly int userNameMaxLength;
        private readonly int emailAddressMaxLength;
        private readonly int accountNameMaxEncryptedLength;
        private readonly int passwordMaxEncryptedLength;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>See <see cref="IDisposable.Dispose"/>.</summary>
        public void Dispose()
        {
            this.resultSet.Dispose();
            this.command.Dispose();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal HostUpdater(SqlCeConnection connection)
        {
            using (var hostCommandGuard =
                ScopeGuard.Create(this.command = CommandHelper.Create(connection, HostNames.Table)))
            using (var hostResultSetGuard =
                ScopeGuard.Create(this.resultSet = this.command.ExecuteResultSet(ResultSetOptions.Updatable)))
            {
                using (var hostSchemaTable = this.resultSet.GetSchemaTable())
                {
                    this.hostNameMaxLength = SqlCeHelper.GetColumnSize(hostSchemaTable, HostNames.NameColumn);
                    this.userNameMaxLength = SqlCeHelper.GetColumnSize(hostSchemaTable, HostNames.UserNameColumn);
                    this.emailAddressMaxLength =
                        SqlCeHelper.GetColumnSize(hostSchemaTable, HostNames.EmailAddressColumn);
                    this.accountNameMaxEncryptedLength =
                        SqlCeHelper.GetColumnSize(hostSchemaTable, HostNames.AccountNameColumn);
                    this.passwordMaxEncryptedLength =
                        SqlCeHelper.GetColumnSize(hostSchemaTable, HostNames.PasswordColumn);
                }

                hostCommandGuard.Dismiss();
                hostResultSetGuard.Dismiss();
            }
        }

        internal int HostNameMaxLength
        {
            get { return this.hostNameMaxLength; }
        }

        internal int UserNameMaxLength
        {
            get { return this.userNameMaxLength; }
        }

        internal int EmailAddressMaxLength
        {
            get { return this.emailAddressMaxLength; }
        }

        internal int AccountNameMaxEncryptedLength
        {
            get { return this.accountNameMaxEncryptedLength; }
        }

        internal int PasswordMaxEncryptedLength
        {
            get { return this.passwordMaxEncryptedLength; }
        }

        internal void UpdateUserName(int hostId, string userName)
        {
            this.Update(hostId, userNameColumn, userName);
        }

        internal void UpdateEmailAddress(int hostId, string emailAddress)
        {
            this.Update(hostId, emailAddressColumn, emailAddress);
        }

        internal void UpdateAccountName(int hostId, byte[] accountName)
        {
            this.Update(hostId, accountNameColumn, accountName);
        }

        internal void UpdatePassword(int hostId, byte[] password)
        {
            this.Update(hostId, passwordColumn, password);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void Update(int hostId, string[] columnNames, params object[] values)
        {
            this.resultSet.Update(new object[] { hostId }, columnNames, values);
        }
    }
}
